import { Controller, Get, Param, Post, Res, Body, Req, Logger, Headers } from "@nestjs/common";
import { Response, Request } from "express";
import { ConfigService } from "../config/config.service";
import { getIsMobile } from "./utils";
import { I18nRequestScopeService } from "nestjs-i18n";
@Controller()
export class LinkController {
    theme = "";
    logo = "";
    favicon = "";
    productName = "";

    constructor(
        private readonly configService: ConfigService,
        private readonly logger: Logger,
        private readonly i18n: I18nRequestScopeService
    ) {}

    //根据linkid获取访问详细信息
    @Get("*")
    async get(@Req() req: Request, @Res() res: Response, @Headers("user-agent") userAgent: string) {
        const id = req.path.slice(6, 40);
        const isMobile = getIsMobile(userAgent);
        const redirectPrefix = isMobile ? "/anyshare/m/link" : "/anyshare/link";
        // if (id.length > 34) {
        //     id = id.substring(0, 34);
        // }
        try {
            // 获取通用配置
            let lastTimestamp = Date.now();
            this.logger.log("{ /eacp/v1/config/getoemconfigbysection GET} start");
            const {
                data: { theme },
            } = await this.configService.eacpPublicApi.post("/eacp/v1/config/getoemconfigbysection", {
                section: "anyshare",
            });
            this.logger.log(`{ /eacp/v1/config/getoemconfigbysection GET} success  +${Date.now() - lastTimestamp}ms`);
            this.theme = theme;
            const section = "shareweb_zh-cn";
            // switch (lang) {
            //     case "zh":
            //     case "zh-cn":
            //         section = "shareweb_zh-cn";
            //         break;
            //     case "zh-tw":
            //     case "zh-hk":
            //         section = "shareweb_zh-tw";
            //         break;
            //     default:
            //         section = "shareweb_en-us";
            //         break;
            // }

            this.logger.log("{ /eacp/v1/config/getoemconfigbysection POST} start");
            // 获取oem配置
            const {
                data: { [`logo.png`]: logo, product, [`favicon.ico`]: favicon },
            } = await this.configService.eacpPublicApi.post("/eacp/v1/config/getoemconfigbysection", { section });
            this.logo = logo;
            this.productName = product;
            this.favicon = favicon;
            this.logger.log(`{ /eacp/v1/config/getoemconfigbysection POST} success  +${Date.now() - lastTimestamp}ms`);
            this.logger.log(`{ /shared-link/v1/links/${id} GET} start`);
            const { data } = await this.configService.sharedLinkPublicApi.get(`/shared-link/v1/links/{link_id}`, {
                params: { link_id: id },
            });
            this.logger.log(`{ /shared-link/v1/links/${id} GET} success  +${Date.now() - lastTimestamp}ms`);

            const { type } = data as any;
            if (type === "anonymous") {
                const {
                    id,
                    item: { belongs_to, type: item_type },
                    title,
                    expires_at,
                    password_required,
                } = data as any;
                if (belongs_to === "document") {
                    //sharedlink匿名访问
                    if (req.cookies && req.cookies[`link_token:${id}`]) {
                        this.logger.log(
                            `redirect to  ${redirectPrefix}/${id}?type=${type}&password_required=${password_required}&title=${title}&expires_at=${encodeURIComponent(
                                expires_at
                            )}&item_type=${item_type}`
                        );

                        //存在token，直接重定向
                        return res.redirect(
                            `${redirectPrefix}/${id}?type=${type}&password_required=${password_required}&title=${title}&expires_at=${encodeURIComponent(
                                expires_at
                            )}&item_type=${item_type}`
                        );
                    } else {
                        //不存在token，判断是否需要密码
                        if (password_required) {
                            // 需要密码，显示输入密码界面
                            return res.render("link-password", {
                                password_tips: await this.i18n.translate(`${"MobileClient.SHARE_PASSWORD_TIPS"}`),
                                id,
                                type,
                                password_required,
                                title,
                                expires_at,
                                item_type,
                                belongs_to,
                                theme,
                                logo,
                                password: "",
                                product,
                                favicon,
                                input_tips: await this.i18n.translate(`${"MobileClient.SHARE_INPUT_TIPS"}`),
                                share_ok: await this.i18n.translate(`${"MobileClient.SHARE_OK"}`),
                            });
                        } else {
                            try {
                                lastTimestamp = Date.now();
                                this.logger.log("{ /authentication/v1/anonymous POST} start");
                                const { data } = await this.configService.authenticationPublicApi.post(
                                    "/authentication/v1/anonymous",
                                    {
                                        client_id: this.configService.hydraInfo.clientId,
                                        redirect_uri: this.configService.hydraInfo.redirectUri,
                                        response_type: "token",
                                        scope: "offline openid all",
                                        credential: {
                                            account: id,
                                            password: "",
                                        },
                                    }
                                );
                                this.logger.log(
                                    `{ /authentication/v1/anonymous POST} success +${Date.now() - lastTimestamp}ms`
                                );
                                if (data) {
                                    const { access_token, expirses_in } = data as any;
                                    res.cookie(`link_token:${id}`, access_token, { maxAge: expirses_in * 1000 });
                                    this.logger.log(
                                        `redirect to ${redirectPrefix}/${id}?type=${type}&password_required=${password_required}&title=${title}&expires_at=${encodeURIComponent(
                                            expires_at
                                        )}&item_type=${item_type}`
                                    );

                                    return res.redirect(
                                        `${redirectPrefix}/${id}?type=${type}&password_required=${password_required}&title=${title}&expires_at=${encodeURIComponent(
                                            expires_at
                                        )}&item_type=${item_type}`
                                    );
                                }
                            } catch (error) {
                                this.logger.error("{ /authentication/v1/anonymous POST}", `${error}`);
                                if (error && error.response && error.response.data) {
                                    const code = error.response.data.code;
                                    switch (code) {
                                        case 403007002:
                                            return res.render("link-err", {
                                                message: await this.i18n.translate(
                                                    `${"MobileClient.SHARE_ACCESSLIMIT"}`
                                                ),
                                            });

                                        default:
                                            return res.render("link-err", {
                                                message: error.response.data.message,
                                            });
                                    }
                                } else {
                                    return res.render("link-err", {
                                        message: await this.i18n.translate(`${"MobileClient.SHARE_UNKHOWNERR"}`),
                                    });
                                }
                            }
                        }
                    }
                } else {
                    //autosheet匿名访问
                    if (req.cookies && req.cookies[`link_token:${id}`]) {
                        //存在token，直接重定向
                        return res.redirect(
                            `/autosheets/link/${id}?type=${type}&password_required=${password_required}&title=${title}&expires_at=${encodeURIComponent(
                                expires_at
                            )}&item_type=${item_type}`
                        );
                    } else {
                        //不存在token，判断是否需要密码
                        if (password_required) {
                            //需要密码，显示密码界面
                            return res.render("link-password", {
                                password_tips: await this.i18n.translate(`${"MobileClient.SHARE_PASSWORD_TIPS"}`),
                                id,
                                type,
                                password_required,
                                title,
                                expires_at,
                                item_type,
                                belongs_to,
                                theme,
                                logo,
                                password: "",
                                product,
                                favicon,
                                input_tips: await this.i18n.translate(`${"MobileClient.SHARE_INPUT_TIPS"}`),
                                share_ok: await this.i18n.translate(`${"MobileClient.SHARE_OK"}`),
                            });
                        } else {
                            //不需要密码,调用换取匿名token方法
                            try {
                                lastTimestamp = Date.now();
                                this.logger.log("{ /authentication/v1/anonymous POST} start");
                                const { data } = await this.configService.authenticationPublicApi.post(
                                    "/authentication/v1/anonymous",
                                    {
                                        client_id: this.configService.hydraInfo.clientId,
                                        redirect_uri: this.configService.hydraInfo.redirectUri,
                                        response_type: "token",
                                        scope: "offline openid all",
                                        credential: {
                                            account: id,
                                            password: "",
                                        },
                                    }
                                );
                                this.logger.log(
                                    `{ /authentication/v1/anonymous POST} success +${Date.now() - lastTimestamp}ms`
                                );
                                if (data) {
                                    const { access_token, expirses_in } = data as any;
                                    res.cookie(`link_token:${id}`, access_token, { maxAge: expirses_in * 1000 });
                                    return res.redirect(
                                        `/autosheets/link/${id}?type=${type}&password_required=${password_required}&title=${title}&expires_at=${encodeURIComponent(
                                            expires_at
                                        )}&item_type=${item_type}`
                                    );
                                }
                            } catch (error) {
                                if (error && error.response && error.response.data) {
                                    const code = error.response.data.code;
                                    switch (code) {
                                        case 403007002:
                                            return res.render("link-err", {
                                                message: await this.i18n.translate(
                                                    `${"MobileClient.SHARE_ACCESSLIMIT"}`
                                                ),
                                            });

                                        default:
                                            return res.render("link-err", {
                                                message: error.response.data.code.message,
                                            });
                                    }
                                } else {
                                    return res.render("link-err", {
                                        message: await this.i18n.translate(`${"MobileClient.SHARE_UNKHOWNERR"}`),
                                    });
                                }
                            }
                        }
                    }
                }
            } else if (type === "realname") {
                const {
                    id,
                    item: { id: itemId, belongs_to, type },
                } = data as any;
                if (belongs_to === "document") {
                    const redirectUrl = `${redirectPrefix}/${id}?type=realname&item_id=${encodeURIComponent(
                        itemId
                    )}&item_type=${type}`;
                    if (isMobile) {
                        //sharedlink实名访问,存在token
                        if (req.cookies && req.cookies[`client.oauth2_token`] && req.cookies[`id_token`]) {
                            return res.redirect(redirectUrl);
                        } else {
                            //sharedlink实名访问,不存在token
                            const state = Buffer.from(redirectUrl).toString("base64");
                            res.cookie("state", state, { httpOnly: true, secure: this.configService.publicInfo.https });
                            return res.redirect(
                                `/oauth2/auth?client_id=${
                                    this.configService.hydraInfo.clientId
                                }&response_type=code&scope=offline+openid+all&redirect_uri=${
                                    this.configService.hydraInfo.redirectUri
                                }&state=${encodeURIComponent(state)}`
                            );
                        }
                    } else {
                        return res.redirect(redirectUrl);
                    }
                } else {
                    //autosheet实名访问
                    if (req.cookies && req.cookies[`client.oauth2_token`] && req.cookies[`id_token`]) {
                        return res.redirect(`/autosheets/link/${id}?type=realname&item_id=${itemId}&item_type=${type}`);
                    } else {
                        const realnameUrl = `/autosheets/link/${id}?type=realname&item_id=${itemId}&item_type=${type}`;
                        const state = Buffer.from(realnameUrl).toString("base64");
                        res.cookie("state", state, { httpOnly: true, secure: this.configService.publicInfo.https });
                        return res.redirect(
                            `/oauth2/auth?client_id=${
                                this.configService.hydraInfo.clientId
                            }&response_type=code&scope=offline+openid+all&redirect_uri=${
                                this.configService.hydraInfo.redirectUri
                            }&state=${encodeURIComponent(state)}`
                        );
                    }
                }
            }
        } catch (error) {
            //链接解析异常
            if (error && error.response && error.response.data) {
                const num = error.response.data.code;
                this.logger.error("{ /eacp/v1/config/getoemconfigbysection GET} err", `${error}`);
                switch (num) {
                    case 400007001:
                        return res.render("link-err", {
                            message: await this.i18n.translate(`${"MobileClient.SHARE_EXPIRED"}`),
                            product: this.productName,
                            favicon: this.favicon,
                        });

                    default:
                        return res.render("link-err", {
                            message: error.response.code,
                            product: this.productName,
                            favicon: this.favicon,
                        });
                }
            } else {
                return res.render("link-err", {
                    message: await this.i18n.translate(`${"MobileClient.SHARE_UNKHOWNERR"}`),
                    product: this.productName,
                    favicon: this.favicon,
                });
            }
        }
    }

    //换取匿名token
    @Post()
    async post(@Res() res: Response, @Body() body, @Headers("user-agent") userAgent: string) {
        const isMobile = getIsMobile(userAgent);
        const redirectPrefix = isMobile ? "/anyshare/m/link" : "/anyshare/link";
        if (body.password === "") {
            return res.render("link-password", {
                password_tips: await this.i18n.translate(`${"MobileClient.SHARE_PASSWORD_TIPS"}`),
                id: body.id,
                type: body.type,
                password_required: body.password_required,
                title: body.title,
                expires_at: body.expires_at,
                item_type: body.item_type,
                belongs_to: body.belongs_to,
                theme: body.theme,
                logo: body.logo,
                password: "",
                product: body.product,
                favicon: body.favicon,
                input_tips: await this.i18n.translate(`${"MobileClient.SHARE_INPUT_TIPS"}`),
                share_ok: await this.i18n.translate(`${"MobileClient.SHARE_OK"}`),
                err_message: await this.i18n.translate(`${"MobileClient.SHARE_NOPASSWORD"}`),
            });
        }
        if (body.belongs_to === "document") {
            //sharedlink匿名换取token需要密码的情况
            try {
                const lastTimestamp = Date.now();
                this.logger.log("{/authentication/v1/anonymous POST} start");
                const { data } = await this.configService.authenticationPublicApi.post("/authentication/v1/anonymous", {
                    client_id: this.configService.hydraInfo.clientId,
                    redirect_uri: this.configService.hydraInfo.redirectUri,
                    response_type: "token",
                    scope: "offline openid all",
                    credential: {
                        account: body.id,
                        password: body.password,
                    },
                });
                this.logger.log(`{/authentication/v1/anonymous POST} success +${Date.now() - lastTimestamp}ms`);
                if (data) {
                    const { access_token, expirses_in } = data as any;
                    res.cookie(`link_token:${body.id}`, access_token, { maxAge: expirses_in * 1000 });
                    return res.redirect(
                        `${redirectPrefix}/${body.id}?type=${body.type}&password_required=${
                            body.password_required
                        }&title=${body.title}&expires_at=${encodeURIComponent(body.expires_at)}&item_type=${
                            body.item_type
                        }`
                    );
                }
            } catch (error) {
                this.logger.error("{/authentication/v1/anonymous POST} err", `${error}`);
                //换取匿名token异常
                if (error.response && error.response.data) {
                    let message: string;
                    switch (error.response.data.code) {
                        case 403007001:
                            message = await this.i18n.translate(`${"MobileClient.SHARE_ERRPASSWORD"}`);
                            break;
                        case 403007002:
                            message = await this.i18n.translate(`${"MobileClient.SHARE_ACCESSLIMIT"}`);
                            break;
                        case 403007003:
                            message = await this.i18n.translate(`${"MobileClient.SHARE_HARE_EXPIRED"}`);
                            break;
                        default:
                            message = error.response.data.message;
                            break;
                    }
                    res.render("link-password", {
                        password_tips: await this.i18n.translate(`${"MobileClient.SHARE_PASSWORD_TIPS"}`),
                        id: body.id,
                        type: body.type,
                        password_required: body.password_required,
                        title: body.title,
                        expires_at: body.expires_at,
                        item_type: body.item_type,
                        belongs_to: body.belongs_to,
                        theme: body.theme,
                        logo: body.logo,
                        err_message: message,
                        password: body.password,
                        product: body.product,
                        favicon: body.favicon,
                        input_tips: await this.i18n.translate(`${"MobileClient.SHARE_INPUT_TIPS"}`),
                        share_ok: await this.i18n.translate(`${"MobileClient.SHARE_OK"}`),
                    });
                }
            }
        } else {
            const lastTimestamp = Date.now();
            this.logger.log("{/authentication/v1/anonymous POST} start");
            //autosheet匿名换取token需要密码的情况
            try {
                const { data } = await this.configService.authenticationPublicApi.post("/authentication/v1/anonymous", {
                    client_id: this.configService.hydraInfo.clientId,
                    redirect_uri: this.configService.hydraInfo.redirectUri,
                    response_type: "token",
                    scope: "offline openid all",
                    credential: {
                        account: body.id,
                        password: body.password,
                    },
                });
                this.logger.log(`{/authentication/v1/anonymous POST} success +${Date.now() - lastTimestamp}ms`);
                if (data) {
                    const { access_token, expirses_in } = data as any;
                    res.cookie(`link_token:${body.id}`, access_token, { maxAge: expirses_in * 1000 });
                    return res.redirect(
                        `/autosheets/link/${body.id}?type=${body.type}&password_required=${
                            body.password_required
                        }&title=${body.title}&expires_at=${encodeURIComponent(body.expires_at)}&item_type=${
                            body.item_type
                        }`
                    );
                }
            } catch (error) {
                //换取匿名token异常
                if (error.response && error.response.data) {
                    let message: string;
                    switch (error.response.data.code) {
                        case 403007001:
                            message = await this.i18n.translate(`${"MobileClient.SHARE_ERRPASSWORD"}`);
                            break;
                        case 403007002:
                            message = await this.i18n.translate(`${"MobileClient.SHARE_ACCESSLIMIT"}`);
                            break;
                        case 403007003:
                            message = await this.i18n.translate(`${"MobileClient.SHARE_HARE_EXPIRED"}`);
                            break;
                        default:
                            message = error.response.data.message;
                            break;
                    }
                    res.render("link-password", {
                        password_tips: await this.i18n.translate(`${"MobileClient.SHARE_PASSWORD_TIPS"}`),
                        id: body.id,
                        type: body.type,
                        password_required: body.password_required,
                        title: body.title,
                        expires_at: body.expires_at,
                        item_type: body.item_type,
                        belongs_to: body.belongs_to,
                        theme: body.theme,
                        logo: body.logo,
                        err_message: message,
                        password: body.password,
                        product: body.product,
                        favicon: body.favicon,
                        input_tips: await this.i18n.translate(`${"MobileClient.SHARE_INPUT_TIPS"}`),
                        share_ok: await this.i18n.translate(`${"MobileClient.SHARE_OK"}`),
                    });
                }
            }
        }
    }
}
